﻿using ScottPlot;
using ScottPlot.PlotStyles;
using System;

namespace UtilZ.Dotnet.ScottPlotEx
{
    internal class PlotHelper
    {
        public static CoordinateRect GetAlignedExtent(PlotAlignedExtentOptions alignedExtentOptions, CoordinateRect extentOrDefault)
        {
            double cellWidth, cellHeight;
            return GetAlignedExtent(alignedExtentOptions, extentOrDefault, out cellWidth, out cellHeight);
        }

        public static CoordinateRect GetAlignedExtent(PlotAlignedExtentOptions alignedExtentOptions, CoordinateRect extentOrDefault, out double cellWidth, out double cellHeight)
        {
            Alignment cellAlignment = Alignment.MiddleCenter;
            if (alignedExtentOptions != null)
            {
                cellAlignment = alignedExtentOptions.CellAlignment;

                if (alignedExtentOptions.CellWidth.HasValue || alignedExtentOptions.CellHeight.HasValue)
                {
                    double left = extentOrDefault.Left;
                    double bottom = extentOrDefault.Bottom;
                    double right, top;

                    if (alignedExtentOptions.CellWidth.HasValue)
                    {
                        right = extentOrDefault.Left + alignedExtentOptions.CellWidth.Value * extentOrDefault.Width;
                    }
                    else
                    {
                        right = extentOrDefault.Right;
                    }

                    if (alignedExtentOptions.CellHeight.HasValue)
                    {
                        top = extentOrDefault.Bottom + alignedExtentOptions.CellHeight.Value * extentOrDefault.Height;
                    }
                    else
                    {
                        top = extentOrDefault.Top;
                    }
                    alignedExtentOptions.Position = new CoordinateRect(left, right, bottom, top);
                }

                if (alignedExtentOptions.Position.HasValue)
                {
                    var position = alignedExtentOptions.Position.Value;
                    //user will provide the extends to the data. The image will be one cell wider and taller so we need to add that on (it is being added on in teh default case).
                    double cellwidth = position.Width / (extentOrDefault.Width - 1);
                    double cellheight = position.Height / (extentOrDefault.Height - 1);

                    if (position.Left < position.Right)
                    {
                        position.Right += cellwidth;
                    }

                    if (position.Left > position.Right)
                    {
                        position.Left -= cellwidth; //cellwidth will be negative if extent is flipped
                    }

                    if (position.Bottom < position.Top)
                    {
                        position.Top += cellheight;
                    }

                    if (position.Bottom > position.Top)
                    {
                        position.Bottom -= cellheight; //cellheight will be negative if extent is inverted
                    }

                    extentOrDefault = position;
                }
            }

            cellWidth = extentOrDefault.Width / extentOrDefault.Width;
            cellHeight = extentOrDefault.Height / extentOrDefault.Height;
            double xOffset = Math.Abs(cellWidth) * cellAlignment.HorizontalFraction();
            double yOffset = Math.Abs(cellHeight) * cellAlignment.VerticalFraction();
            var cellOffset = new Coordinates(-xOffset, -yOffset);
            return extentOrDefault.WithTranslation(cellOffset);
        }

        public static PlotScaleInfo GetScale(IAxes axes, int bitmapWidth, int bitmapHeight)
        {
            CoordinateRangeMutable xrange = axes.XAxis.Range;
            CoordinateRangeMutable yrange = axes.YAxis.Range;
            var scaleX = bitmapWidth / xrange.Span;
            var scaleY = bitmapHeight / yrange.Span;

            //Loger.Info($"XAxisShowRange:{Math.Round(xrange.Min, 2)}-{Math.Round(xrange.Max, 2)},Span:{Math.Round(xrange.Span, 2)}    " +
            //    $" YAxisShowRange:{Math.Round(yrange.Min, 2)}-{Math.Round(yrange.Max, 2)}, Span:{Math.Round(yrange.Span, 2)}");

            return new PlotScaleInfo(scaleX, scaleY, bitmapWidth, bitmapHeight);
        }
    }

    internal struct PlotScaleInfo
    {
        public readonly double ScaleX;
        public readonly double ScaleY;
        public readonly int BitmapWidth;
        public readonly int BitmapHeight;

        public PlotScaleInfo(double scaleX, double scaleY, int bitmapWidth, int bitmapHeight)
        {
            this.ScaleX = scaleX;
            this.ScaleY = scaleY;
            this.BitmapWidth = bitmapWidth;
            this.BitmapHeight = bitmapHeight;
        }

        public double GetMax()
        {
            return Math.Max(this.ScaleX, this.ScaleY);
        }

        public double GetMin()
        {
            return Math.Min(this.ScaleX, this.ScaleY);
        }

    }
}
